using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using Gratamira.AccesoDato;

namespace Gratamira.CapaNegocio
{
    public class MoviInve
    {
        StringCollection mSql = new StringCollection();
        #region propiedades
        private string _TipoMovID;
        private DateTime _Fecha;
        private int _Numero;
        private string _DocumentoRef;
        private string _BodegaID;
        private string _BodegaDestino;
        private char _IndReserva;
        private string _ReservaID;
        private Int32 _TerceroID;
        private string _NombreTercero;
        private string _Observacion;
        private claseMovimiento _ClaseMovimiento;
        private string _CodUsuCre;
        private DateTime _FecHorCre;
        private string _UsuUltMod;
        private DateTime _FecUltMod;

        public string TipoMovID
        {
            get { return _TipoMovID; }
            set { _TipoMovID = value; }
        }
        public DateTime Fecha
        {
            get { return _Fecha; }
            set { _Fecha = value; }
        }
        public int Numero
        {
            get { return _Numero; }
            set { _Numero = value; }
        }
        public string DocumentoRef
        {
            get { return _DocumentoRef; }
            set { _DocumentoRef = value; }
        }
	    public string BodegaID
	    {
		    get { return _BodegaID;}
		    set { _BodegaID = value;}
	    }
        public string BodegaDestino
        {
            get { return _BodegaDestino; }
            set { _BodegaDestino = value; }
        }
        public char IndReserva
        {
            get { return _IndReserva; }
            set { _IndReserva = value; }
        }
        public string ReservaID
        {
            get { return _ReservaID; }
            set { _ReservaID = value; }
        }
        public Int32 TerceroID
	    {
		    get { return _TerceroID;}
		    set { _TerceroID = value;}
	    }
        public string NombreTercero
        {
            get { return _NombreTercero; }
            set { _NombreTercero = value; }
        }
        public string Observacion
        {
            get { return _Observacion; }
            set { _Observacion = value; }
        }
        public claseMovimiento ClaseMovimiento
        {
            get { return _ClaseMovimiento; }
            set { _ClaseMovimiento = value; }
        }
        public string CodUsuCre
        {
            get { return _CodUsuCre; }
            set { _CodUsuCre = value; }
        }
        public DateTime FecHorCre
        {
            get { return _FecHorCre; }
            set { _FecHorCre = value; }
        }
        public string UsuUltMod
        {
            get { return _UsuUltMod; }
            set { _UsuUltMod = value; }
        }
        public DateTime FecUltMod
        {
            get { return _FecUltMod; }
            set { _FecUltMod = value; }
        }
        #endregion Propiedades

        #region Constructores
        public MoviInve()
        {  }
        public MoviInve(DataSet dsDatos, string pBodegaID, int pNumero)
        {
            //Constructor para Edicion de Maestra y Detalle del Movimiento
            BodegaID = pBodegaID;
            Numero = pNumero;
            string strSql = "SELECT M.*, T.Nombre NombreTercero FROM Movimiento M " +
                            " JOIN Tercero T ON M.TerceroID = T.TerceroID " +
                            " WHERE BodegaID = '" + BodegaID + "'" +
                            " AND NumMovID = " + Numero;
            DataTable dt = new DataTable();
            accesoDatos p = new accesoDatos();
            dt = p.leerDatosSQL(strSql, "");
            dt.TableName = "Movimiento";
            dsDatos.Tables.Add(dt);
            //leerRegistro();
            //Llenar el Dataset con los datos del detalle de este registro
            string tSql = "SELECT D.ProductoID, P.Nombre, D.Cantidad, P.UnidadManejoID Unidad, '0' Existencia, '0' Reservado, '0' Disponible, P.Estado " +
                          " FROM DetMov D JOIN Producto P ON D.ProductoID = P.ProductoID " +
                          " WHERE BodegaID = '" + BodegaID + "'" +
                          " AND NumMovID = " + Numero +
                          " ORDER BY D.ProductoID";
            DataTable dtTabla = new DataTable();
            dtTabla = p.leerDatosSQL(tSql,"");
            dtTabla.TableName = "DetMov";
            ////Crear restriccion de no repetir producto en el detalle
            DataColumn col = new DataColumn();
            col = dtTabla.Columns["ProductoID"];
            UniqueConstraint restriccion = new UniqueConstraint("RefUnica",col);
            dtTabla.Constraints.Add(restriccion);
            dsDatos.Tables.Add(dtTabla);
        }
        #endregion Constructores
        
        #region Metodos publicos
        public bool insertarMovimiento(DataSet dsDatos)
        {
            //Iniciar vbles de auditoria
            CodUsuCre = UsuUltMod;
            FecHorCre = FecUltMod;
            //Instanciar el string SQL que se enviara a la Base de datos
            mSql.Clear();
            //Insertar nuevo movimiento de inventarios
            asignarRegistro(dsDatos);
            //Generar consecutivo para la bodega origen
            Numero =  leerConsecutivo() + 1;
            dsDatos.Tables["Movimiento"].Rows[0]["NumMovID"] = Numero;
            //Crear cadenas de datos del registro a insertar
            insertarRegistro(dsDatos);
            if (TipoMovID == "S00")
            { 
                //Es una Salida x Transferenca. Crear el registro de Entrada x transferencia
                BodegaID = BodegaDestino;
                Observacion = "Entrada x transferencia creada automaticamente por la Salida : " + Numero;
                Numero = leerConsecutivo() + 1;
                TipoMovID = "E00";
                ClaseMovimiento = claseMovimiento.Entrada;
                //Buscar existencias en la bodega destino
                leerExistenciasDetalle(dsDatos);
                insertarRegistro(dsDatos);
            }
            //Enviar comandos SQL en una transaccion
            accesoDatos p = new accesoDatos();
            p.ejecutarLoteSQL(mSql);
            return true;
        }
        public bool actualizarRegistro(DataSet dsDatos)
        {
            //Instanciar el string SQL que se enviara a la Base de datos
            //Actualizar registro encabezado
            asignarRegistro(dsDatos);
            string tSql = "UPDATE Movimiento SET " +
                          "Observacion = '" + Observacion + "'" +
                          ",UsuUltMod = '" + UsuUltMod + "'" +
                          ",FecUltMod = '" + FecUltMod.ToString("MM/dd/yyyy HH:mm") + "' " +
                          " WHERE (BodegaID = '" + BodegaID + "'" +
                          " AND NumMovID = " + Numero + ")";
            accesoDatos p = new accesoDatos();
            int res = p.ejecutarSQL(tSql, "");
            if (res>0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public void asignarDetalleReserva(DataSet dsDatos)
        {
            string strSql = "SELECT R.ProductoID, R.Saldo, " + 
                " P.Nombre, P.UnidadManejoID, P.Estado, S.Existencia " +
                " FROM DETRES R JOIN PRODUCTO P ON R.ProductoID = P.ProductoID " +
                " JOIN SALDOS S ON S.ProductoID = R.ProductoID " +
                " WHERE R.ReservaID = '" + ReservaID + "'" +
                " AND S.BodegaID = '" + BodegaID + "'" +
                " AND R.Saldo > 0 " +
                " ORDER BY R.ProductoID";
            DataTable dt = new DataTable();
            accesoDatos p = new accesoDatos();
            dt = p.leerDatosSQL(strSql, "");
            //borrar filas del detalle en el dataset
            dsDatos.Tables["DetMov"].Rows.Clear();
            //Se inserta una fila en el detalle del movimiento por cada fila en el resultado
            foreach (DataRow fila in dt.Rows)
            {
                DataRow nuevaFila = dsDatos.Tables["DetMov"].NewRow();
                nuevaFila["ProductoID"] = fila["ProductoID"];
                nuevaFila["Nombre"] = fila["Nombre"];
                nuevaFila["Unidad"] = fila["UnidadManejoID"];
                nuevaFila["Existencia"] = fila["Existencia"];
                nuevaFila["Reservado"] = fila["Saldo"];
                if (Convert.ToDouble(fila["Existencia"]) >= Convert.ToDouble(fila["Saldo"]))
                {
                    //El disponible es el Saldo de la reserva
                    nuevaFila["Disponible"] = fila["Saldo"];
                    nuevaFila["Cantidad"] = fila["Saldo"];
                }
                else
                {
                    //El disponible es la existencias en bodega
                    nuevaFila["Disponible"] = fila["Existencia"];
                    nuevaFila["Cantidad"] = fila["Existencia"];
                }
                nuevaFila["Estado"] = fila["Estado"];
                dsDatos.Tables["DetMov"].Rows.Add(nuevaFila);
            }
        }

        public void leerExistenciasDetalle(DataSet dsDatos)
        {
            Producto p = new Producto();
            //Para cada fila en el detalle
            foreach (DataRow fila in dsDatos.Tables["DetMov"].Rows)
            {
                p.ProductoID = fila["ProductoID"].ToString();
                if (p.leerSaldoBodega(BodegaID))
                {
                    fila["Existencia"] = p.SaldoEnBodega;
                    fila["Reservado"] = p.Reserva;
                    fila["Disponible"] = p.SaldoEnBodega - p.Reserva;
                }
            }
        }
        public DataTable leerMovimiento(string pMes, string pAnno, string pBodega, string pTipoMov)
        {
            //Llamado desde la consulta de Movimiento
            string strSql = "SELECT Mov.NumMovID as Movimiento, Mov.Fecha, TipMov.Tipo, TipMov.Nombre, Mov.Observacion " +
                " FROM Movimiento AS Mov " +
                " INNER JOIN tipoMovimiento AS TipMov ON Mov.TipoMovID = TipMov.TipoMovID " +
                " WHERE month(Mov.Fecha) = '" + pMes + "' and year(Mov.Fecha) = '" + pAnno + "'  AND " +
                " Mov.BodegaID = '" + pBodega + "' ";
            if (pTipoMov == claseMovimiento.Entrada.ToString())
            {
                strSql += "AND TipMov.Tipo = '" + claseMovimiento.Entrada.ToString() + "'";
            }
            else if (pTipoMov == claseMovimiento.Salida.ToString())
            {
                strSql += "AND TipMov.Tipo = '" + claseMovimiento.Salida.ToString() + "'";
            }
            DataTable dt = new DataTable();
            accesoDatos p = new accesoDatos();
            try
            {
                dt = p.leerDatosSQL(strSql, "");
                if (p.regAfectados <= 0)
                {
                    throw new Exception("No hay datos que mostrar.");
                }
                return dt;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public DataTable leerMovimientoProveedor(string pNombreTercero, string pBodegaID, string pFechaInicial, string pFechaFinal)
        {
            string strSql = "SELECT Mov.NumMovID as Movimiento, Mov.Fecha, Ter.Nombre as [Nombre Tercero], TipMov.Tipo, TipMov.Nombre FROM Movimiento AS Mov " +
                            " INNER JOIN tipoMovimiento AS TipMov ON Mov.TipoMovID = TipMov.TipoMovID " +
                            " INNER JOIN tercero ter ON mov.terceroid = ter.terceroid " +
                            " WHERE ter.nombre LIKE '%" + pNombreTercero + "%' AND mov.bodegaid = '" + pBodegaID + "' " +
                            " AND mov.fecha BETWEEN '" + pFechaInicial + "' AND '" + pFechaFinal + "' ";


            DataTable dt = new DataTable();
            accesoDatos p = new accesoDatos();
            try
            {
                dt = p.leerDatosSQL(strSql, "");

                if (p.regAfectados <= 0)
                {
                    throw new Exception("No hay datos que mostrar.");
                }

                return dt;
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }

        #endregion Metodos publicos

        #region Metodos Privados
        private void asignarRegistro(DataSet dsDatos)
        {
            //Asignar los valores de la fila a las propiedades de la clase
            DataRow fila = dsDatos.Tables["Movimiento"].Rows[0];
            BodegaID = fila["BodegaID"].ToString();
            //fila["NumMovID"] = leerConsecutivo(BodegaID) + 1;
            //Numero = Convert.ToInt32(fila["NumMovID"]);
            Fecha = Convert.ToDateTime(fila["Fecha"]);
            TipoMovID = fila["TipoMovID"].ToString();
            DocumentoRef = fila["DocumentoRef"].ToString();
            TerceroID = Convert.ToInt32(fila["TerceroID"]);
            Observacion = fila["Observacion"].ToString();
        }
        private bool insertarRegistro(DataSet dsDatos)
        {
            mSql.Add("INSERT INTO Movimiento " +
                "(NumMovID,BodegaID,TipoMovID,DocumentoRef,TerceroID, Fecha,Observacion," + 
                "CodUsuCre,FecHorCre,UsuUltMod,FecUltMod) " +
                "VALUES (" + Numero + ",'" + BodegaID + "','" + TipoMovID + "'" +
                ", '" + DocumentoRef + "'," + TerceroID +
                ", '" + Fecha.ToString("MM/dd/yyyy") + "'" +
                ",'" + Observacion + "'" + 
                ",'" + CodUsuCre + "'" +
                ",'" + FecHorCre.ToString("MM/dd/yyyy HH:mm") + "'" +
                ",'" + UsuUltMod + "'" +
                ",'" + FecUltMod.ToString("MM/dd/yyyy HH:mm") + "')");
            //Salvar el detalle del Movimiento de Inventario
            foreach (DataRow fila in dsDatos.Tables["DetMov"].Rows)
            {
                //Para cada registro en el detalle se debe crear una sentencia INSERT
                insertarFilaDetalle(fila);
                //Actualizar saldo 
                actualizarSaldo(fila);
            }
            //Actualizar consecutivo
            actualizarConsecutivo();
            return true;
        }    
        private void insertarFilaDetalle(DataRow pFila)
        {
            string pCantidad = Utilidades.convertirComaPunto(Convert.ToDouble(pFila["Cantidad"]));
            //Crear el string para insertar una fila en el detalle usando los valores por parametros
            mSql.Add("INSERT INTO DetMov " +
                    "(NumMovID,BodegaID, ProductoID, Cantidad) " +
                    "VALUES (" + Numero + ",'" + BodegaID + "'" +
                    ",'" + pFila["ProductoID"].ToString() + "'" +
                    "," + pCantidad + ")");
        }
        private void actualizarSaldo(DataRow pFila)
        {
            string tCantidad = Utilidades.convertirComaPunto(Convert.ToDouble(pFila["Cantidad"]));
            string tCantMovi = tCantidad;
            if (Convert.ToDouble(pFila["Existencia"]) == -1)
            {
                //Crear el string para insertar un registro de saldo en la bodega, para el producto
                mSql.Add("INSERT INTO Saldos " +
                        "(BodegaID, ProductoID, Existencia) " +
                        "VALUES ('" + BodegaID + "'" +
                        ",'" + pFila["ProductoID"].ToString() + "'" +
                        "," + tCantidad + ")");
            }
            else
            {
                if (ClaseMovimiento == claseMovimiento.Salida)
                {
                    //Disminuir el saldo en las salidas
                    tCantMovi = "(-" + tCantidad + ")";
                }
                //Crear el string para actualizar el saldo de la bodega, para el producto
                mSql.Add("UPDATE Saldos " +
                        " SET Existencia = Existencia + " + tCantMovi + 
                        " WHERE BodegaID = '" + BodegaID + "'" +
                        " AND ProductoID = '" + pFila["ProductoID"].ToString() + "'");
                if (ClaseMovimiento == claseMovimiento.Salida && IndReserva == 'S')
                {
                    //Actualizar saldo de la reserva
                    mSql.Add("UPDATE DetRes " +
                            " SET Saldo = Saldo - " + tCantidad +
                            " ,Utilizado = Utilizado + " + tCantidad +
                            " WHERE ReservaID = '" + ReservaID + "'" +
                            " AND ProductoID = '" + pFila["ProductoID"].ToString() + "'");
                }
            }
        }
        private int leerConsecutivo()
        {
            string tSql = "SELECT NumMovMax FROM Bodega WHERE BodegaID = '" + BodegaID + "'";
            accesoDatos p = new accesoDatos();
            return int.Parse(p.leerValorSQL(tSql, ""));
        }
        private void actualizarConsecutivo()
        {
            mSql.Add("UPDATE Bodega SET NumMovMax = " + Numero +
                     " WHERE BodegaID = '" + BodegaID + "'");
            if (ClaseMovimiento == claseMovimiento.Salida && IndReserva == 'S')
            {
                //Actualizar estado de la reserva
                mSql.Add("UPDATE Reserva " +
                        " SET Estado = 'T'" +
                        " WHERE Estado = 'C' " +
                        " AND ReservaID IN " +
                        "(SELECT ReservaID FROM DetRes group by ReservaID Having Sum(Saldo) = 0)");
            }
        }
        #endregion Metodos Privados
    }
}
